
/***
 * Functions to read and write raw DSA image sequence files.
 *
 */

#ifndef DSAIO_H
#define DSAIO_H

#include <fstream>
#include <iostream>

using namespace std;

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageRegionConstIterator.h"
#include "itkRawImageIO.h"

typedef unsigned char DsaPixel;
typedef itk::Image< DsaPixel, 2 > DsaFrame;

/**
 * Appends a frame to the end of a raw DSA file.
 */
void dsa_append_frame ( char *file_name, DsaFrame::Pointer frame )
{
  ofstream file_stream;
  file_stream.open ( file_name, ios::binary | ios::app );
  if ( ! file_stream.is_open() )
  {
    cerr << "Error: Could not read file '" << file_name << "'" << endl;
    return;
  }
  
  // send data
  typedef itk::ImageRegionConstIterator< DsaFrame > ConstIterator;
  DsaFrame::RegionType region = frame->GetLargestPossibleRegion();
  ConstIterator inputIt ( frame, region );
  for ( inputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt )
  {
    file_stream << inputIt.Get();
  }
  
  file_stream.close();
  return;
}

/**
 * Frames are numbered from 0 to frame_count-1.
 */
DsaFrame::Pointer dsa_get_frame ( char *file_name, int frame,
                                  int width = 512, int height = 512 )
{
  // Raw image reader
  typedef itk::RawImageIO< DsaPixel, 2 > ImageIO;	
  ImageIO::Pointer imageIO = ImageIO::New ( );
  unsigned int dim [ 2 ] = { width, height };
  double spacing [ 3 ] = { 1.0, 1.0 };
  double origin [ 3 ] = { 0.0, 0.0 };
  for ( int i = 0; i < 2; i ++ ) {
    imageIO->SetDimensions ( i, dim [ i ] );
    imageIO->SetSpacing ( i, spacing [ i ] );
    imageIO->SetOrigin ( i, origin [ i ] );
  }
  int bytes_to_skip = frame * height * width;
  imageIO->SetHeaderSize( bytes_to_skip );
  imageIO->SetNumberOfComponents( 1 );
  
  // File reader
  typedef itk::ImageFileReader< DsaFrame > ReaderType;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetImageIO( imageIO );
  reader->SetFileName( file_name );
  
  // Read DSA
  reader->Update ( );
  DsaFrame::Pointer ret = reader->GetOutput();
  return ret;
}
 
 
/**
 * @return int frame count in DSA file or -1 on IO error
 */
int dsa_frame_count ( char *file_name, int width = 512, int height = 512 )
{
  // open file
  ifstream file_stream;
  file_stream.open ( file_name );
  if ( ! file_stream.is_open() )
  {
    cerr << "Error: Could not read file '" << file_name << "'" << endl;
    return -1;
  }
  
  // check file length
  file_stream.seekg ( 0, ios::end );
  if ( ( int ) file_stream.tellg() % ( width * height ) != 0 )
  {
    cerr << "Error: Length invalid of file '" << file_name << "'" << endl;
    return -1;
  }
  
  // compute frame count
  int frame_count = file_stream.tellg() / ( width * height );
  
  file_stream.close();
  
  return frame_count;
}

#endif
